<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        function InterceptorManager() {
            this.handlers = []
        }
        InterceptorManager.prototype.use = function (fulfilled, rejected) {
            this.handlers.push({
                fulfilled,
                rejected
            })
        }
        function Axios(config) {
            this.defaults = config;
            this.interceptors = {
                request: new InterceptorManager(),
                response: new InterceptorManager()
            }
        }

        Axios.prototype.request = function (config) {
            // 请求的核心方法，dispatchRequest => 是函数，返回值是 promise对象
            let dispatchRequest = (config)=>{
                return Promise.resolve('我是请求回来的数据');
            }
            // 初始化 chain
            let chain = [dispatchRequest, undefined];
            // 添加请求拦截，其实就是向chain数组前面追加元素
            this.interceptors.request.handlers.forEach(item=>{
                chain.unshift(item.fulfilled,item.rejected);
            })
            // 添加响应拦截器
            this.interceptors.response.handlers.forEach(item=>{
                chain.push(item.fulfilled,item.rejected);
            })
            // 启动链条的调用
            let promise = Promise.resolve(config);
            while(chain.length){
                promise = promise.then(chain.shift(), chain.shift())
            }
            return promise;
        }
        let methods = ['get', 'post', 'delete', 'put', 'patch'];
        methods.forEach(method => {
            Axios.prototype[method] = () => {
                return this.request(config);
            }
        })
        // createInstance
        function createInstance(config) {
            // 1. 使用Axios.prototype.request创造 instance
            // 2. 将 Axios.prototype原型上的方法，都加载 instance身上
            // 3. 将 new Axios() 实例对象的属性也加载 instance身上

            //创建 Axios实例对象
            const context = new Axios(config);
            // 创建instance实例
            const instance = Axios.prototype.request.bind(context);
            console.log(Object.keys(Axios.prototype));
            // 将 Axios.prototype原型上的方法，都加载 instance身上
            Object.keys(Axios.prototype).forEach(method => {
                instance[method] = Axios.prototype[method]
            })
            // 将Axios 实例对象的属性[defaults , interceptors]也加载 instance身上
            Object.keys(context).forEach(attr => {
                instance[attr] = context[attr];
            })
            return instance;
        }
        const axios = createInstance({ method: 'post' });
        // 将Axios类添加到 axios上，成为他的一个属性
        axios.Axios = Axios;
        // 创建create方法。 create方法之所以可以进行多站点配置，因为它也是执行createInstance 创建的。
        axios.create = function (config) {
            return createInstance(config);
        }

        // 测试添加拦截器
        axios.interceptors.request.use(config1 => {
            return config1;
        }, error1 => {
            return Promise.reject(error);
        });

        axios.interceptors.response.use(config1=>{
            return config1;
        },error1=>{
            return Promise.reject(error);
        })

        axios({
            method:'get'
        })
        
        .then(value=>{
            console.log('value',value);
        })
        

        // console.dir(Axios);
    </script>
</body>

</html>